"""
SQL语义分析器 V2.0
完全符合实践要求：表/列存在性检查、类型一致性检查、列数/列序检查
"""

class SemanticError:
    """语义错误类"""
    
    def __init__(self, error_type, position, reason):
        self.error_type = error_type
        self.position = position
        self.reason = reason
    
    def __repr__(self):
        return f"[{self.error_type}, {self.position}, {self.reason}]"

class SemanticAnalyzerV2:
    """SQL语义分析器 V2.0"""
    
    def __init__(self):
        """初始化语义分析器"""
        self.catalog = {}  # 系统目录，存储表结构信息
        self.errors = []   # 存储语义错误
    
    def analyze(self, ast):
        """分析AST的语义"""
        self.errors = []
        
        if not ast:
            self.add_error("SYNTAX_ERROR", "AST", "空的AST")
            return None
        
        if ast['type'] == 'CREATE_TABLE':
            return self.analyze_create_table(ast)
        elif ast['type'] == 'INSERT':
            return self.analyze_insert(ast)
        elif ast['type'] == 'SELECT':
            return self.analyze_select(ast)
        elif ast['type'] == 'UPDATE':
            return self.analyze_update(ast)
        elif ast['type'] == 'DELETE':
            return self.analyze_delete(ast)
        else:
            self.add_error("UNKNOWN_STATEMENT", "AST", f"未知的语句类型: {ast['type']}")
            return None
    
    def analyze_create_table(self, ast):
        """分析CREATE TABLE语句"""
        table_name = ast['table_name']
        
        # 检查表名是否已存在
        if table_name in self.catalog:
            self.add_error("TABLE_EXISTS", table_name, f"表 '{table_name}' 已存在")
            return None
        
        # 验证列定义
        columns = {}
        primary_keys = []
        
        for col_def in ast['columns']:
            col_name = col_def['name']
            
            # 检查列名重复
            if col_name in columns:
                self.add_error("COLUMN_DUPLICATE", col_name, f"列 '{col_name}' 重复定义")
                continue
            
            # 验证数据类型
            if not self.validate_data_type(col_def['type']):
                self.add_error("INVALID_TYPE", col_name, f"无效的数据类型: {col_def['type']}")
                continue
            
            columns[col_name] = col_def
            
            # 收集主键
            if col_def.get('primary_key'):
                primary_keys.append(col_name)
        
        # 验证主键
        if len(primary_keys) > 1:
            self.add_error("MULTIPLE_PRIMARY_KEY", "PRIMARY KEY", "只能有一个主键列")
            return None
        
        # 创建表结构
        table_schema = {
            'columns': columns,
            'primary_key': primary_keys[0] if primary_keys else None,
            'indexes': {}
        }
        
        self.catalog[table_name] = table_schema
        
        return {
            'type': 'CREATE_TABLE',
            'table_name': table_name,
            'schema': table_schema,
            'status': 'SUCCESS'
        }
    
    def analyze_insert(self, ast):
        """分析INSERT语句"""
        table_name = ast['table_name']
        
        # 检查表是否存在
        if table_name not in self.catalog:
            self.add_error("TABLE_NOT_EXISTS", table_name, f"表 '{table_name}' 不存在")
            return None
        
        table_schema = self.catalog[table_name]
        columns = list(table_schema['columns'].keys())
        values = ast['values']
        
        # 检查值的数量
        if len(values) != len(columns):
            self.add_error("VALUE_COUNT_MISMATCH", "VALUES", 
                          f"值的数量({len(values)})与列数({len(columns)})不匹配")
            return None
        
        # 验证值的类型
        for i, (col_name, value) in enumerate(zip(columns, values)):
            col_def = table_schema['columns'][col_name]
            if not self.validate_value_type(value, col_def['type']):
                self.add_error("TYPE_MISMATCH", col_name, 
                              f"列 '{col_name}' 的值类型不匹配，期望 {col_def['type']['type']}")
                continue
        
        return {
            'type': 'INSERT',
            'table_name': table_name,
            'values': values,
            'columns': columns,
            'status': 'SUCCESS'
        }
    
    def analyze_select(self, ast):
        """分析SELECT语句"""
        table_name = ast['table_name']
        
        # 检查表是否存在
        if table_name not in self.catalog:
            self.add_error("TABLE_NOT_EXISTS", table_name, f"表 '{table_name}' 不存在")
            return None
        
        table_schema = self.catalog[table_name]
        columns = list(table_schema['columns'].keys())
        
        # 验证选择的列
        if ast['columns'] != '*':
            for col in ast['columns']:
                if col not in columns:
                    self.add_error("COLUMN_NOT_EXISTS", col, f"列 '{col}' 不存在")
                    continue
        
        # 分析WHERE条件
        where_condition = None
        if ast['where']:
            where_condition = self.analyze_condition(ast['where'], table_schema)
        
        return {
            'type': 'SELECT',
            'table_name': table_name,
            'columns': ast['columns'],
            'where': where_condition,
            'schema': table_schema,
            'status': 'SUCCESS'
        }
    
    def analyze_update(self, ast):
        """分析UPDATE语句"""
        table_name = ast['table_name']
        
        # 检查表是否存在
        if table_name not in self.catalog:
            self.add_error("TABLE_NOT_EXISTS", table_name, f"表 '{table_name}' 不存在")
            return None
        
        table_schema = self.catalog[table_name]
        
        # 验证SET子句
        for assignment in ast['assignments']:
            col_name = assignment['column']
            if col_name not in table_schema['columns']:
                self.add_error("COLUMN_NOT_EXISTS", col_name, f"列 '{col_name}' 不存在")
                continue
            
            # 验证值的类型
            col_def = table_schema['columns'][col_name]
            if not self.validate_value_type(assignment['value'], col_def['type']):
                self.add_error("TYPE_MISMATCH", col_name, 
                              f"列 '{col_name}' 的值类型不匹配")
                continue
        
        # 分析WHERE条件
        where_condition = None
        if ast['where']:
            where_condition = self.analyze_condition(ast['where'], table_schema)
        
        return {
            'type': 'UPDATE',
            'table_name': table_name,
            'assignments': ast['assignments'],
            'where': where_condition,
            'schema': table_schema,
            'status': 'SUCCESS'
        }
    
    def analyze_delete(self, ast):
        """分析DELETE语句"""
        table_name = ast['table_name']
        
        # 检查表是否存在
        if table_name not in self.catalog:
            self.add_error("TABLE_NOT_EXISTS", table_name, f"表 '{table_name}' 不存在")
            return None
        
        table_schema = self.catalog[table_name]
        
        # 分析WHERE条件
        where_condition = None
        if ast['where']:
            where_condition = self.analyze_condition(ast['where'], table_schema)
        
        return {
            'type': 'DELETE',
            'table_name': table_name,
            'where': where_condition,
            'schema': table_schema,
            'status': 'SUCCESS'
        }
    
    def analyze_condition(self, condition, table_schema):
        """分析WHERE条件"""
        if isinstance(condition, dict):
            if condition['type'] in ['AND', 'OR']:
                left = self.analyze_condition(condition['left'], table_schema)
                right = self.analyze_condition(condition['right'], table_schema)
                return {
                    'type': condition['type'],
                    'left': left,
                    'right': right
                }
            elif condition['type'] == 'NOT':
                operand = self.analyze_condition(condition['operand'], table_schema)
                return {
                    'type': 'NOT',
                    'operand': operand
                }
            elif condition['type'] in ['EQ', 'NE', 'LT', 'LE', 'GT', 'GE']:
                left = self.analyze_expression(condition['left'], table_schema)
                right = self.analyze_expression(condition['right'], table_schema)
                return {
                    'type': condition['type'],
                    'left': left,
                    'right': right
                }
        
        return condition
    
    def analyze_expression(self, expr, table_schema):
        """分析表达式"""
        if isinstance(expr, dict) and expr.get('type') == 'binary_op':
            left = self.analyze_expression(expr['left'], table_schema)
            right = self.analyze_expression(expr['right'], table_schema)
            return {
                'type': 'binary_op',
                'operator': expr['operator'],
                'left': left,
                'right': right
            }
        elif isinstance(expr, str) and '.' not in expr:
            # 列引用
            if expr not in table_schema['columns']:
                self.add_error("COLUMN_NOT_EXISTS", expr, f"列 '{expr}' 不存在")
                return expr
        elif isinstance(expr, str) and '.' in expr:
            # 表.列引用
            table_name, col_name = expr.split('.', 1)
            if table_name not in self.catalog:
                self.add_error("TABLE_NOT_EXISTS", table_name, f"表 '{table_name}' 不存在")
                return expr
            if col_name not in self.catalog[table_name]['columns']:
                self.add_error("COLUMN_NOT_EXISTS", col_name, f"列 '{col_name}' 不存在")
                return expr
        
        return expr
    
    def validate_data_type(self, data_type):
        """验证数据类型"""
        if isinstance(data_type, dict):
            type_name = data_type['type']
            if type_name in ['int', 'float', 'boolean']:
                return True
            elif type_name == 'varchar':
                return 'length' in data_type and isinstance(data_type['length'], int)
        return False
    
    def validate_value_type(self, value, data_type):
        """验证值的类型"""
        if value is None:
            return True  # NULL值总是允许的
        
        if isinstance(data_type, dict):
            type_name = data_type['type']
            if type_name == 'int':
                return isinstance(value, int)
            elif type_name == 'float':
                return isinstance(value, (int, float))
            elif type_name == 'boolean':
                return isinstance(value, bool)
            elif type_name == 'varchar':
                return isinstance(value, str) and len(value) <= data_type.get('length', 255)
        
        return False
    
    def add_error(self, error_type, position, reason):
        """添加错误信息"""
        error = SemanticError(error_type, position, reason)
        self.errors.append(error)
    
    def get_errors(self):
        """获取错误列表"""
        return self.errors
    
    def has_errors(self):
        """检查是否有错误"""
        return len(self.errors) > 0
    
    def get_catalog(self):
        """获取系统目录"""
        return self.catalog
    
    def print_catalog(self):
        """打印系统目录"""
        print("系统目录:")
        for table_name, table_schema in self.catalog.items():
            print(f"  表: {table_name}")
            print(f"    主键: {table_schema['primary_key']}")
            print("    列:")
            for col_name, col_def in table_schema['columns'].items():
                print(f"      {col_name}: {col_def['type']}")
    
    def print_errors(self):
        """打印错误信息"""
        if self.has_errors():
            print("语义错误:")
            for error in self.errors:
                print(f"  {error}")
        else:
            print("语义分析通过")

# 测试函数
if __name__ == "__main__":
    analyzer = SemanticAnalyzerV2()
    
    # 测试用例
    test_ast = {
        'type': 'CREATE_TABLE',
        'table_name': 'student',
        'columns': [
            {'name': 'id', 'type': {'type': 'int'}, 'primary_key': True},
            {'name': 'name', 'type': {'type': 'varchar', 'length': 50}},
            {'name': 'age', 'type': {'type': 'int'}}
        ]
    }
    
    result = analyzer.analyze(test_ast)
    analyzer.print_errors()
    if not analyzer.has_errors():
        print("语义分析成功")
        analyzer.print_catalog()
